﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Forms;
using System.Xml;

namespace Ezhu.WPFWin
{
    /// <summary>
    /// LoadText.xaml 的交互逻辑
    /// </summary>
    public partial class LoadText : Window
    {
        public LoadText()
        {
            InitializeComponent();
        }

        private void GetXML1_Click(object sender, RoutedEventArgs e)
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load("C:/Users/sytm041/Desktop/wpf/WPFWin/WPFWin/text.xml");
            XmlNodeList root = xmldoc.SelectNodes("//maskRoi");
            XmlNode data = root[0].SelectSingleNode("data");
            XmlNode rows = root[0].SelectSingleNode("rows");
            XmlNode cols = root[0].SelectSingleNode("cols");
            System.Text.ASCIIEncoding enconding = new System.Text.ASCIIEncoding();
            byte[] doc = enconding.GetBytes(data.InnerText.Replace("\r\n", ""));
            Bitmap map = ToGrayBitmap(doc,Convert.ToInt32(rows.InnerText), Convert.ToInt32(cols.InnerText));
            img3.Source = BitmapToBitmapSource(map);
            //   img3 = img;

        }
        #region  将Bitmap转换ImageSource
        [DllImport("gdi32.dll", SetLastError = true)]
        private static extern bool DeleteObject(IntPtr hObject);
        //将 Bitmap转换为BitmapSource
        //使用过System.Drawing.Bitmap后一定要用DeleteObject释放掉对象，不然内存不释放，很快系统内存就消耗光了。
        public static System.Windows.Media.ImageSource BitmapToBitmapSource(System.Drawing.Bitmap bitmap)
        {
            IntPtr hBitmap = bitmap.GetHbitmap();
            System.Windows.Media.ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                hBitmap,
                IntPtr.Zero,
                System.Windows.Int32Rect.Empty,
                System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
            if (!DeleteObject(hBitmap))//记得要进行内存释放。否则会有内存不足的报错。
            {
                throw new System.ComponentModel.Win32Exception();
            }

            return wpfBitmap;
        }
        #endregion

        #region 淘汰方法
        //byte[] 转图片    
        public static Bitmap BytesToBitmap(byte[] Bytes)
        {
            MemoryStream stream = null;
            try
            {
                stream = new MemoryStream(Bytes);
                return new Bitmap(new Bitmap(stream));
            }
            catch (ArgumentNullException ex)
            {
                throw ex;
            }
            catch (ArgumentException ex)
            {
                throw ex;
            }
            finally
            {
                stream.Close();
            }
        }

        //图片转byte[]     
        public static byte[] BitmapToBytes(Bitmap Bitmap)
        {
            MemoryStream ms = null;
            try
            {
                ms = new MemoryStream();
                Bitmap.Save(ms, Bitmap.RawFormat);
                byte[] byteImage = new Byte[ms.Length];
                byteImage = ms.ToArray();
                return byteImage;
            }
            catch (ArgumentNullException ex)
            {
                throw ex;
            }
            finally
            {
                ms.Close();
            }
        }
        #endregion

        /// <summary>
        /// 像素点阵转换为bitmap
        /// </summary>
        /// <param name="rawValues">byte[]数组</param>
        /// <param name="width">图片的宽度</param>
        /// <param name="height">图片的高度</param>
        /// <returns>bitmap图片</returns>
        public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height)
        {
            Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
            BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
            //// 获取图像参数  
            //bmpData.Stride = width;
            int stride = bmpData.Stride;  // 扫描线的宽度  
            int offset = stride - width;  // 显示宽度与扫描线宽度的间隙  
            IntPtr iptr = bmpData.Scan0;  // 获取bmpData的内存起始位置  
            int scanBytes = stride * height;// 用stride宽度，表示这是内存区域的大小  
                                            //// 下面把原始的显示大小字节数组转换为内存中实际存放的字节数组  
            int posScan = 0, posReal = 0;// 分别设置两个位置指针，指向源数组和目标数组  
            byte[] pixelValues = new byte[scanBytes];  //为目标数组分配内存  
            for (int x = 0; x < height; x++)
            {
                //// 下面的循环节是模拟行扫描  
                for (int y = 0; y < width; y++)
                {
                    if (posReal == rawValues.Length)
                    {
                        break;
                    }
                    pixelValues[posScan++] = rawValues[posReal++];
                }
                posScan += offset;  //行扫描结束，要将目标位置指针移过那段“间隙”  
            }
            //// 用Marshal的Copy方法，将刚才得到的内存字节数组复制到BitmapData中  
            System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);
            bmp.UnlockBits(bmpData);  // 解锁内存区域  
                                      //// 下面的代码是为了修改生成位图的索引表，从伪彩修改为灰度  
            ColorPalette tempPalette;
            using (Bitmap tempBmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed))
            {
                tempPalette = tempBmp.Palette;
            }
            for (int i = 0; i < 256; i++)
            {
                tempPalette.Entries[i] = System.Drawing.Color.FromArgb(i, i, i);
            }

            bmp.Palette = tempPalette;
            
            //// 算法到此结束，返回结果  
            return bmp;
            
        }

    }
}
